/**
 * 使用typescript+axios重新封装，简化http请求
 */
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'
import { Token } from './constant'


// 定义常量配置信息
const RequestConfig = {
  baseUrl: import.meta.env.VITE_SERVER_API as string,
  timeout: 15000, // 超时时间
  tokenName: Token.TokenName as string,
  successCode: 0  // 请求成功后后端返回给前端的标记码
}

type Result<T> = {
  code: number
  message: string
  data?: T
}

// 定义http请求class
class Request {
  instance: AxiosInstance // 定义axios实例

  constructor(config?: AxiosRequestConfig) {
    this.instance = axios.create(config) // 实例化instance 
    // 添加请求拦截器
    this.instance.interceptors?.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 设置token
        const token = localStorage.getItem(RequestConfig.tokenName) as string
        if (token) {
          config.headers!.Authorization = token
        }
        config.baseURL = RequestConfig.baseUrl
        config.timeout = RequestConfig.timeout
        return config
      }, (err: any) => {
        console.error('request error',err)
        return Promise.reject(err) // 请求错误
      }
    )
    // 添加响应拦截器
    this.instance.interceptors.response.use(
      (resp: AxiosResponse) => {
        //成功回调
        const ret: Result<any> = resp.data
        if (ret.code != RequestConfig.successCode) {
          ElMessage({
            type: 'error',
            message: ret.message
          })
          return
        }
        return ret.data
      }, (error: any) => {
        //http状态码
        const statusCode = error.response.status
        let message = this.handleErrorCode(statusCode)
        if (message == undefined || message == '') {
          message = '网络出现问题'
        }
        //提示错误信息
        ElMessage({
          type: 'error',
          message,
        })
        console.error('response error',error)
        return Promise.reject(error)
      }
    )
  }
  // 处理http code 设置常见错误码
  handleErrorCode(code: number) {
    const map = new Map<number, string>()
    map.set(400, '错误的请求')
    map.set(401, '未授权，请重新登录')
    map.set(403, '拒绝访问')
    map.set(404, '请求错误,未找到该资源')
    map.set(405, '请求方法未允许')
    map.set(408, '请求超时')
    map.set(500, '服务器端出错')
    map.set(501, '网络未实现')
    map.set(502, '网络错误')
    map.set(503, '服务不可用')
    map.set(504, '网络超时')
    map.set(505, 'http版本不支持该请求')
    return map.get(code)
  }

  /* 常用请求封装 */ 
  get<T>(url: string, params?: object): Promise<Result<T>> {
    if(params){
      return this.instance.get(url,{params});
    }else{
      return this.instance.get(url);
    }
  
  }
  post<T>(url: string, data?: object): Promise<Result<T>> {
    return this.instance.post(url, data);
  }
  put<T>(url: string, data?: object): Promise<Result<T>> {
    return this.instance.put(url, data);
  }
  delete<T>(url: string): Promise<Result<T>> {
    return this.instance.delete(url);
  }
  // 文件上传 
  upload<T>(url:string,params?:object):Promise<Result<T>>{
    return this.instance.post(url,params,{
      headers:{
        'Content-Type':'multipart/form-data'
      }
    })
  }
}

//对外暴露
export default new Request({})
